// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.linqingying.gitcode.authentication

import com.fasterxml.jackson.databind.PropertyNamingStrategies
import com.intellij.collaboration.auth.services.OAuthCredentialsAcquirer
import com.intellij.collaboration.auth.services.OAuthCredentialsAcquirerHttp
import com.intellij.util.Url
import com.linqingying.gitcode.authentication.GCOAuthService.Companion.jacksonMapper
import kotlinx.datetime.Instant


internal class GCOAuthCredentialsAcquirer(
    private val giteeAppCred: GCAccountsUtil.GCAppCredentials,
    private val authorizationCodeUrl: Url
) : OAuthCredentialsAcquirer<GCCredentials> {

    override fun acquireCredentials(code: String): OAuthCredentialsAcquirer.AcquireCredentialsResult<GCCredentials> {
        val tokenUrl = ACCESS_TOKEN_URL.addParameters(
            mapOf(
                "grant_type" to authGrantType,
                "client_id" to giteeAppCred.clientId,
                "client_secret" to giteeAppCred.clientSecret,
                "redirect_uri" to authorizationCodeUrl.toExternalForm(),
                "code" to code,

                )
        )

        return OAuthCredentialsAcquirerHttp.requestToken(tokenUrl) { body, _ ->
            val responseData = with(jacksonMapper) {
                propertyNamingStrategy = PropertyNamingStrategies.SnakeCaseStrategy()
                readValue(body, AuthorizationResponseData::class.java)
            }

            GCCredentials(
                responseData.access_token,
                responseData.refresh_token,
                responseData.expires_in,
//                responseData.tokenType,
                responseData.scope,

                Instant.parse(responseData.created_at).epochSeconds
            )
        }
    }
//    {
//        "access_token" : "uygrwNeDFqaxBsm8eSZ3JEs-",
//        "expires_in" : 604234,
//        "refresh_token" : "6ac82953a78843f7865a4ecd04eed4cf",
//        "scope" : "all_user all_key",
//        "created_at" : "2024-12-24T14:00:13.064Z"
//    }
    private data class AuthorizationResponseData(
        val access_token: String,
        val refresh_token: String,
        val expires_in: Long,
//        val tokenType: String,
        val scope: String,
        val created_at: String
    )

    companion object {
        private const val authGrantType = "authorization_code"

        private val ACCESS_TOKEN_URL: Url
            get() = GCOAuthService.SERVICE_URL.resolve("token")
    }
}
